home *** CD-ROM | disk | FTP | other *** search
- #define NAME "xPK"
- #define REVISION "3"
-
- /* Programmheader
-
- Name: xPK
- Author: SDI (before 1.2 Urban Dominik Müller)
- Distribution: PD
- Description: General XPK file-to-file packer/unpacker
- Compileropts: -
- Linkeropts: -l xpkmaster
-
- 1.0 : first public release
- 1.1 : docs written, version string added
- 1.2 19.10.96 : fixed an recursion error
- 1.3 29.11.96 : recompiled
- */
-
- #include "SDI_defines.h"
- #define SDI_TO_ANSI
- #include "SDI_ASM_STD_protos.h"
- #include <pragma/exec_lib.h>
- #include <pragma/dos_lib.h>
- #include <pragma/xpkmaster_lib.h>
- #include <exec/memory.h>
-
- #ifdef __MAXON__
- #define __asm
- #define __saveds
- #endif
-
- #define lines[1000]
-
- ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
- STRPTR tempname(STRPTR);
- STRPTR basename(STRPTR);
- void doarg(STRPTR);
- STRPTR dofile(STRPTR, struct FileInfoBlock *);
- void end(STRPTR);
- LONG isexecutable(STRPTR);
-
- struct Hook chunkhook = {{0}, (ULONG (*) ()) chunkfunc};
- struct Library *XpkBase = 0;
- UBYTE errbuf[300],
- *err = 0,
- namebuf[200],
- PrevName[100],
- strbuf[200];
- struct FileInfoBlock *fib = 0;
-
- UBYTE usage[] =
- "Usage: XPK [-efrsux] [-m method] [-p password] files\n"
- " -e = extract files (same as -u)\n"
- " -f = force packing of already packed files\n"
- " -m = four letter packing method name\n"
- " -p = encrypt/decrypt using password\n"
- " -r = recursively (un)pack files in dir\n"
- " -s = add suffix and don't delete original\n"
- " -x = pack executables only\n";
-
- UBYTE suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
- STRPTR password = 0, method = 0;
-
- void main(int argc, char **argv)
- {
- STRPTR c;
- LONG i = 1;
-
- if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
- !(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
- end("Cannot open " XPKNAME "\n");
-
- if(stricmp(basename(argv[0]), "XPK"))
- method = basename(argv[0]);
- else if(argc < 2 || !strcmp (argv[1], "?"))
- end(usage);
-
- for(; *argv[i] == '-'; i++)
- for(c = argv[i] + 1; *c; c++)
- {
- switch (*c)
- {
- case 'p': password = argv[++i]; break;
- case 'm': method = argv[++i]; break;
- case 's': suffix = 1; break;
- case 'f': force = 1; break;
- case 'e':
- case 'u': unpack = 1; break;
- case 'r': recurse = 1; break;
- case 'x': executables = 1; break;
- default: end(usage);
- }
- if(i >= argc)
- end(usage);
- }
-
- if(!method && !unpack)
- end("Need a packing method, use -m\n");
-
- if(i == argc)
- end(usage);
-
- for(; i < argc && !err; i++)
- doarg(argv[i]);
-
- end(err);
- }
-
- void iprint(STRPTR s)
- {
- ULONG out = Output(), i;
- for(i = depth; i; --i)
- Write(out, " ", 2);
- Write(out, s, strlen(s));
- }
-
- void doarg(STRPTR name)
- {
- ULONG lock;
-
- if(*name == 0xFF)
- return;
-
- if(!(lock = Lock(name, ACCESS_READ)))
- {
- sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
- return;
- }
-
- if(!Examine(lock, fib))
- {
- UnLock(lock);
- sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
- return;
- }
-
- if(fib->fib_DirEntryType < 0)
- {
- UnLock(lock);
- dofile(name, fib);
- }
- else if(recurse)
- {
- ULONG prev;
-
- sprintf(strbuf, "Directory %s\n", name);
- iprint(strbuf);
- prev = CurrentDir(lock);
- *PrevName = 0xFF;
-
- while(ExNext(lock, fib) && !err)
- {
- if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
- err = " *** Break";
- else
- {
- STRPTR thisname;
- ULONG i = strlen(fib->fib_FileName) + 1;
-
- if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
- {
- Write(Output(), "Not enough memory\n", 18);
- break;
- }
- CopyMem(fib->fib_FileName, thisname, i);
- depth++;
- doarg(PrevName);
- depth--;
- strcpy(PrevName, thisname);
- FreeMem(thisname, i);
- }
- }
- depth++;
- doarg(PrevName);
- depth--;
- *PrevName = 0xFF;
-
- UnLock(CurrentDir(prev));
- }
- }
-
- STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
- {
- struct XpkFib xfib;
- UBYTE buf[100];
- LONG len;
-
- if(!force || unpack)
- {
- #ifdef __MAXON__ /* Maxon has no tagcall pragma now */
- struct TagItem t[] = { /* and I don't want to use a link */
- #else /* library */
- if(XpkExamineTags(&xfib,
- #endif
- XPK_InName, (ULONG) filename,
- TAG_DONE
- #ifdef __MAXON__
- , 0 };
- if(XpkExamine(&xfib, t
- #endif
- ))
- {
- sprintf(buf, "Error examining %s\n", filename);
- iprint(buf);
- return 0;
- }
- }
-
- tempname(filename);
- if(!unpack)
- {
- if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
- {
- sprintf(buf, "Skipping (already packed) %s\n", filename);
- iprint(buf);
- return 0;
- }
-
- if(executables && !isexecutable(filename))
- return 0;
-
- if(suffix)
- sprintf(namebuf, "%s.xpk", filename);
-
- {
- #ifdef __MAXON__ /* Maxon has no tagcall pragma now */
- struct TagItem t[] = { /* and I don't want to use a link */
- #else /* library */
- if(XpkPackTags(
- #endif
- XPK_InName, (ULONG) filename,
- XPK_OutName, (ULONG) namebuf,
- XPK_ChunkHook, (ULONG) &chunkhook,
- XPK_GetError, (ULONG) errbuf,
- XPK_PackMethod, (ULONG) method,
- XPK_Password, (ULONG) password,
- XPK_NoClobber, TRUE,
- TAG_DONE
- #ifdef __MAXON__
- , 0 };
- if(XpkPack(t
- #endif
- ))
- {
- ULONG i = strlen(errbuf);
- errbuf[i] = '\n'; errbuf[i+1] = '\0';
- return err = errbuf;
- }
- }
- }
- else
- {
- if(xfib.xf_Type != XPKTYPE_PACKED)
- {
- sprintf(buf, "Skipping (already unpacked) %s\n", filename);
- iprint(buf);
- return 0;
- }
-
- len = strlen(filename);
- suffix = 0;
- if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
- {
- strcpy(namebuf, filename);
- namebuf[len - 5] = 0;
- suffix = 1;
- }
-
- {
- #ifdef __MAXON__ /* Maxon has no tagcall pragma now */
- struct TagItem t[] = { /* and I don't want to use a link */
- #else /* library */
- if(XpkUnpackTags(
- #endif
- XPK_InName, (ULONG) filename,
- XPK_FileName, (ULONG) filename,
- XPK_OutName, (ULONG) namebuf,
- XPK_ChunkHook, (ULONG) &chunkhook,
- XPK_Password, (ULONG) password,
- XPK_GetError, (ULONG) errbuf,
- XPK_NoClobber, TRUE,
- TAG_DONE
- #ifdef __MAXON__
- , 0 };
- if(XpkUnpack(t
- #endif
- ))
- {
- ULONG i = strlen(errbuf);
- errbuf[i] = '\n'; errbuf[i+1] = '\0';
- return err = errbuf;
- }
- }
- }
-
- if(!suffix)
- {
- if(!DeleteFile(filename))
- return err = "Cannot delete input file\n";
- if(!Rename(namebuf, filename))
- return err = "Cannot rename tempfile\n";
- if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
- return err = "Cannot set original comment\n";
- if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
- return err = "Cannot set original protection bits\n";
- }
- }
-
- ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
- {
- ULONG out = Output();
- UBYTE buf[180];
-
- if(prog->xp_Type == XPKPROG_START)
- Write(out, "\033[0 p", 5);
-
- if(prog->xp_Type != XPKPROG_END)
- sprintf(buf,
- "%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
- prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
- prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
- else
- sprintf(buf,
- "%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
- prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
- prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
-
- iprint(buf);
-
- if(prog->xp_Type == XPKPROG_END)
- Write(out, "\033[1 p", 5);
-
- return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
- }
-
- STRPTR tempname(STRPTR name)
- {
- strcpy(namebuf, name);
- for(name = namebuf + strlen (namebuf); name > namebuf; name--)
- if(name[-1] == '/' || name[-1] == ':')
- break;
- sprintf(name, "tmp%lx", &name);
- return namebuf;
- }
-
- LONG isexecutable(STRPTR name)
- {
- ULONG fh;
- BPTR buf[5];
- UBYTE msg[100];
- LONG len;
-
- if(!(fh = Open(name, MODE_OLDFILE)))
- {
- sprintf(msg, "Cannot open %s\n", name);
- iprint(msg);
- return 0;
- }
- len = Read(fh, (void *) buf, 20);
- Close(fh);
-
- if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
- {
- sprintf(msg, "%s not executable\n", name);
- iprint(msg);
- return 0;
- }
-
- if(buf[3] != 0 || buf[4] + 1 != buf[2])
- {
- sprintf(msg, "%s overlayed\n", name);
- iprint(msg);
- return 0;
- }
- return 1;
- }
-
- STRPTR basename(STRPTR name)
- {
- STRPTR ret = name;
-
- for(; *name; ++name)
- {
- if(*name == ':' || *name == '/')
- ret = name + 1;
- }
- return ret;
- }
-
- void end(STRPTR text)
- {
- if(text) Write(Output(), text, strlen(text));
- if(XpkBase) CloseLibrary(XpkBase);
- if(fib) FreeMem(fib, sizeof(struct FileInfoBlock));
-
- exit(text ? 10 : 0);
- }
-